/**
 * @module useStorageWithExpiry
 * @description 提供支持有效期的通用本地存储工具函数，兼容浏览器和 uni-app（微信小程序等）。
 */

/**
 * @interface StorageWithExpiryOptions
 * @description 存储操作参数
 */
export interface StorageWithExpiryOptions {
  /**
   * 存储键名
   */
  key: string
  /**
   * 需要存储的值，仅在 isSave 为 true 时需要
   */
  value?: unknown
  /**
   * 过期时间，单位毫秒。如 60 * 60 * 1000 表示 1 小时；不传表示永久有效
   */
  expire?: number
  /**
   * 浏览器下的存储类型，默认为 localStorage，仅在浏览器环境有效
   */
  storageType?: 'local' | 'session'
  /**
   * 是否为写入操作，true 表示 set，false 表示 get
   */
  isSave?: boolean
}

/**
 * @interface ExpirableData
 * @description 本地存储的数据结构，支持设置有效期和时间戳。
 */
interface ExpirableData {
  /**
   * 实际存储的值
   */
  value: unknown

  /**
   * 到期时间的时间戳（单位：毫秒），为 undefined 表示永久有效
   * @example 1657700000000
   */
  expiry?: number

  /**
   * 存入数据的时间戳（单位：毫秒），用于调试或未来功能扩展
   * @example 1657696400000
   */
  timestamp: number
}

/**
 * 判断是否在浏览器环境
 */
const isBrowser = (): boolean => typeof window !== 'undefined' && typeof localStorage !== 'undefined'

/**
 * 支持设置过期时间的跨平台本地存储工具
 *
 * @template T 返回数据类型
 * @param {StorageWithExpiryOptions} options 存储操作参数
 * @returns {(T | void)} 获取时返回值，写入时无返回
 *
 * @example
 * // 写入数据（1小时过期）
 * useStorageWithExpiry({
 *   key: 'user',
 *   value: { name: '爱宇阳' },
 *   expire: 60 * 60 * 1000, // 1小时
 *   isSave: true,
 * })
 *
 * @example
 * // 读取数据（自动判断是否过期）
 * const user = useStorageWithExpiry<{ name: string }>({
 *   key: 'user',
 * })
 */
export function useStorageWithExpiry<T = unknown>(options: StorageWithExpiryOptions): T | void {
  const {key, value, expire, storageType = 'local', isSave = false} = options
  const now = Date.now()

  const encode = (data: unknown): string => JSON.stringify(data)
  const decode = (data: string | null): ExpirableData | null => {
    if (!data) return null
    try {
      return JSON.parse(data)
    } catch {
      return null
    }
  }

  // 写入数据
  if (isSave) {
    const data: ExpirableData = {
      value,
      expiry: expire ? now + expire : undefined,
      timestamp: now,
    }

    if (isBrowser()) {
      const storage = storageType === 'local' ? localStorage : sessionStorage
      storage.setItem(key, encode(data))
    } else if (typeof uni !== 'undefined') {
      uni.setStorageSync(key, encode(data))
    }

    return
  }

  // 读取数据
  let stored: ExpirableData | null = null

  if (isBrowser()) {
    const storage = storageType === 'local' ? localStorage : sessionStorage
    stored = decode(storage.getItem(key))
  } else if (typeof uni !== 'undefined') {
    stored = decode(uni.getStorageSync(key))
  }

  if (stored) {
    if (stored.expiry && now > stored.expiry) {
      // 已过期，清除数据
      if (isBrowser()) {
        const storage = storageType === 'local' ? localStorage : sessionStorage
        storage.removeItem(key)
      } else if (typeof uni !== 'undefined') {
        uni.removeStorageSync(key)
      }
      return null as unknown as T
    }

    return stored.value as T
  }

  return null as unknown as T
}

export default useStorageWithExpiry;
